#ifndef _TEMPLET_MODULE_ringmult
#define _TEMPLET_MODULE_ringmult

#include <string.h>
#include <assert.h>

#include "tet.h"

/*$TET$ringmult$!include!*/
#include <iostream>
using namespace std;

const int N=2;
/*$TET$*/

namespace ringmult{

class Link:public TEMPLET::Channel{
public:
	Link(TEMPLET::Assemble*a);
	~Link();
public:
	struct cli{Link*c;}_cli;
	struct srv{Link*c;}_srv;
public:
	struct col{//<BEG> 
/*$TET$Link$col*/
		double b[N];
		int c;
/*$TET$*/
	};
	struct ready{//<PROC> 
/*$TET$Link$ready*/
/*$TET$*/
	};
public:
	void _send_col();
	void _send_ready();
public:
	col* _get_col(){return &_mes_col;}
	ready* _get_ready(){return &_mes_ready;}
private:
	Link::col  _mes_col;
	Link::ready  _mes_ready;
private:
	enum _state_Iface{
		_st_BEG,
		_st_PROC
	};
	enum _sent_Iface{_no_snt,
		_snt_col,
		_snt_ready
	};
private:
	enum _state_Iface _state;
	enum _sent_Iface _sent;
public:
	// access tests for message 'col'
	bool _s_in_col(){return _active==SRV && _sent==_snt_col;}
	bool _c_in_col(){return _active==CLI && _sent==_snt_col;}
	bool _s_out_col(){return _active==SRV && (false);}
	bool _c_out_col(){return _active==CLI && (_state==_st_BEG||false);}
	// access tests for message 'ready'
	bool _s_in_ready(){return _active==SRV && _sent==_snt_ready;}
	bool _c_in_ready(){return _active==CLI && _sent==_snt_ready;}
	bool _s_out_ready(){return _active==SRV && (_state==_st_PROC||false);}
	bool _c_out_ready(){return _active==CLI && (false);}
};

class Proc:public TEMPLET::Process{
public:
	Proc(TEMPLET::Assemble*a);
	~Proc();
private:
	//methods
	bool beg(/*out*/Link::col*p1);
	bool send(/*in*/Link::ready*p1,/*out*/Link::col*p2);
	bool proc(/*in*/Link::col*p1,/*out*/Link::ready*p2);

/*$TET$Proc$!userdata!*/
public:
	double a[N],b[N],c[N];
	int row,col;
	int n;
	bool empty;
/*$TET$*/

public:
	enum{
		_port_l,
		_port_r,
		_method_beg,
		_method_send,
		_method_proc
	};
public:
	void p_l(Link::srv*p){_l=(Link*)p->c;_l->_srvPort=this;_l->_srv_selector=_port_l;}
	void p_r(Link::cli*p){_r=(Link*)p->c;_r->_cliPort=this;_r->_cli_selector=_port_r;}
protected:
	virtual void _run(int _selector,TEMPLET::Channel*_channel);
private:
	// ports
	Link* _l;
	Link* _r;
	// initial activator
	TEMPLET::Activator* _entry;
};

class ringmult:public TEMPLET::Assemble{
public:
	ringmult(int NT);
	~ringmult();

/*$TET$ringmult$!userdata!*/
/*$TET$*/
public:
	Proc*new_Proc(){Proc*p=new Proc(this);_regProc(p);return p;}
	void new_Link(Link::cli*&c,Link::srv*&s){Link*ch=new Link(this);_regChan(ch);
		ch->_cli.c=ch->_srv.c=ch;c=&ch->_cli;s=&ch->_srv;}
};

}
#endif
